
/* GCSx
** LAYEREDIT.H
**
** Layer editor-only functionality
*/

/*****************************************************************************
** Copyright (C) 2003-2006 Janson
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
*****************************************************************************/

#ifndef __GCSx_LAYEREDIT_H_
#define __GCSx_LAYEREDIT_H_

// (should never be used as a SaveLoad item- always called from a scene;
//  doesn't follow spec exactly- cachedContent(), etc.)
class LayerEdit : public Layer /* , virtual public SaveLoad */ {
protected:
    // Has the scene been modified from initial state (from empty if new)
    int headerModified;
    int contentModified;
    int disassociated;

    // Set us (and our scene) as modified
    void setHeaderModified();
    
    // Sets any tiles above a given number to 0; must be uncached/locked
    void clearTilesAbove(int code);

    // In edit mode, spawns get locked too
    int doLock(int play) throw_File;
    int doUnlock(int play);

public:
    // Sets us (and scene) as modified; called by our spawn points
    void setContentModified();

    // Creates a default properties (empty) layer
    // World and ID may be NULL/0 if in process of creating  (but scene is required)
    LayerEdit(class WorldEdit* myWorld, class Scene* myScene, int myId = 0);
    ~LayerEdit();

    // Intended only for use after creating/importing- not in general usage
    void setInfo(class WorldEdit* myWorld, int newId);

    void loadHeader(class FileRead* file) throw_File;
    void disassociate() throw_File;
    void reassociate();
    
    class WorldEdit* getWorldEdit() { return dynamic_cast<WorldEdit*>(world); }
    const class WorldEdit* getWorldEdit() const { return dynamic_cast<WorldEdit*>(world); }
    class SceneEdit* getSceneEdit() { return dynamic_cast<SceneEdit*>(scene); }
    class TileSetEdit* getTileSetEdit() { return dynamic_cast<TileSetEdit*>(tileset); }
    int getSpawnCount() const { return spawns.size(); }
    class SpawnEdit* getSpawn(int pos); // NOT an ID

    // Change properties
    void setName(const std::string& newName, Window* srcWin = NULL, Window* exWin = NULL) throw_Undo;
    // (changing to another type deletes all data)
    // Must be uncached (scene must therefore be uncached/locked)
    void setType(LayerType newType, Window* srcWin = NULL, Window* exWin = NULL) throw_Undo;
    // Works for ANY type of layer; works even if not allocated
    // Must be uncached (scene must therefore be uncached/locked)
    // ptrs are used by undo/redo calling us; standard use can ignore
    void setSize(int newX, int newY, Window* srcWin = NULL, Window* exWin = NULL, Uint32** undo1 = NULL, Uint32** undo2 = NULL, Uint32** undo3 = NULL) throw_Undo;
    
    // Pointer becomes owned by us
    void addSpawn(class SpawnEdit* newSpawn, Window* srcWin = NULL, Window* exWin = NULL) throw_Undo throw_File;
    void deleteSpawn(class SpawnEdit* delSpawn, Window* srcWin = NULL, Window* exWin = NULL) throw_Undo;
    
    // Intended for display in editor; coordinates are the chunk to display, in pixels
    // and the offset on the surface to display to; handles all layer types; assumes
    // appropriate clipping rectangle is set, as pixels outside the given area MAY be
    // drawn; dim blits at 50% alpha; must be uncached/locked
    void blit(int pX, int pY, int pW, int pH, int offsetX, int offsetY, struct SDL_Surface* dest, int dim = 0);
    // Display sprites (call after blit*())
    void blitSpawns(int pX, int pY, int pW, int pH, int offsetX, int offsetY, struct SDL_Surface* dest, const std::set<int>* selected = NULL, int dim = 0);
    
    // LAYER_TILE layers
    // Must be uncached (scene must therefore be uncached/locked)
    // Throws file exceptions if new tileset err'd when uncaching
    void setTileset(int newTilesetId, Window* srcWin = NULL, Window* exWin = NULL) throw_Undo;
    // Must be uncached (scene must therefore be uncached/locked)
    void setExtended(int newUsesExtended, Window* srcWin = NULL, Window* exWin = NULL) throw_Undo;
    // Must be uncached (scene must therefore be uncached/locked)
    void setEffects(int newUsesEffects, Window* srcWin = NULL, Window* exWin = NULL) throw_Undo;
    // Must be uncached (scene must therefore be uncached/locked)
    // Gets raw data
    const Uint32* getTileData() const { return tileData; }
    const Uint32* getExtendedData() const { return extendedData; }
    const Uint32* getEffectsData() const { return effectsData; }

    // Copies tile layer (or partial) asserts rect is clipped to layer size already
    // exWin is window to exempt from resulting update event; does NOT handle undo
    // Must be uncached (scene must therefore be uncached/locked)
    // Fx pointers may be NULL; pitch is number of Uint32s, usually same as layer width
    // dest/fx ptrs point directly to destination- x/y from rect is not added in
    void loadLayer(Uint32* dest, Uint32* destExt, Uint32* destFx, int destPitch, const Rect& rect) const;
    void saveLayer(const Uint32* source, const Uint32* sourceExt, const Uint32* sourceFx, int sourcePitch, const Rect& rect, Window* exWin);
    // (all three ptrs are optional, but at least one is required; no exempt window as always called from undo anyway)
    void swapLayer(Uint32* data, Uint32* dataExt, Uint32* dataFx, int dataPitch, const Rect& rect);
    
    // Helper function for displaying a tile layer in editor
    // see blit() for parameters; made public so editor can use it's own data
    // NULL dataExt for no extended; width/height are layer size
    // Selection parameters are optional, allows editor to overlay a floating selection
    static void blitTileLayer(const TileSetEdit* tileset, const Uint32* data, const Uint32* dataExt, int width, int height, int pX, int pY, int pW, int pH, int offsetX, int offsetY, struct SDL_Surface* dest, int dim = 0, const Uint32* selData = NULL, const Uint32* selDataExt = NULL, int selXOffs = 0, int selYOffs = 0, int selWidth = -1);
    
    // Returns true if OK pressed
    // Only allows changing of layer type if isNew
    // Handles locking/uncaching scene
    int propertiesDialog(int isNew, LayerType defaultType = LAYER_TILE, Window* srcWin = NULL, Window* exWin = NULL);

    // Modified?
    int isHeaderModified() const;
    int isContentModified() const;
    void saveSuccess(); // (merely clears modified flags)
    
    // Save data to file
    Uint32 saveHeader(class FileWrite* file) throw_File;
    void saveContent(class FileWrite* file) throw_File;
    void cachedContent(FileRead* file, int oldData);
};

#endif
